Skip to content

Feat: Seed remote feature flag controller with default flags - #9747

Merged
Cal-L merged 5 commits into
mainfrom
feat/seed-defaults-remote-feature-flag-controller
Aug 7, 2026
Merged

Feat: Seed remote feature flag controller with default flags#9747
Cal-L merged 5 commits into
mainfrom
feat/seed-defaults-remote-feature-flag-controller

Conversation

@Cal-L

@Cal-L Cal-L commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Explanation

This is part of an effort to keep the RemoteFeatureFlagController as the source of truth for feature flags. As part of that effort, we've added a new optional constructor arg named defaultFeatureFlags, which will be provided by the platform apps. Under the hood, the controller will account for these flags when processing the effective flags that the consumers will use. The order of priority for the flags are - default flags > remote flags > override flags.

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Low Risk
Additive optional API with centralized merge logic and broad test coverage; behavior change is limited to consumers that pass defaults or rely on override removal without a remote value.

Overview
Adds an optional defaultFeatureFlags constructor option so platform apps can seed RemoteFeatureFlagController with client-side defaults that are not persisted. Effective flags exposed in remoteFeatureFlags are now merged through #getEffectiveFeatureFlags with precedence defaults → processed remote → local overrides.

Remote fetch, override set/remove/clear, and constructor hydration all use that helper so defaults remain for flags the server omits, remote values win on conflicts, and removing an override falls back to remote or default when no remote value exists. The wallet initializer forwards instanceOptions.remoteFeatureFlagController.defaultFeatureFlags into the controller.

Reviewed by Cursor Bugbot for commit 615b161. Bugbot is set up for automated code reviews on this repo. Configure here.

@Cal-L
Cal-L requested review from a team as code owners July 31, 2026 18:55
@Cal-L
Cal-L temporarily deployed to default-branch July 31, 2026 18:56 — with GitHub Actions Inactive
Comment thread packages/remote-feature-flag-controller/src/remote-feature-flag-controller.ts Outdated
Comment thread packages/remote-feature-flag-controller/src/remote-feature-flag-controller.ts Outdated
Comment thread packages/remote-feature-flag-controller/src/remote-feature-flag-controller.ts Outdated
Comment thread packages/remote-feature-flag-controller/src/remote-feature-flag-controller.ts Outdated
Comment thread packages/remote-feature-flag-controller/src/remote-feature-flag-controller.ts Outdated
Comment thread packages/remote-feature-flag-controller/src/remote-feature-flag-controller.ts Outdated
Comment thread packages/remote-feature-flag-controller/src/remote-feature-flag-controller.ts Outdated
@Cal-L
Cal-L force-pushed the feat/seed-defaults-remote-feature-flag-controller branch from 2b81ab9 to 8ce7cc1 Compare August 4, 2026 22:57
weitingsun
weitingsun previously approved these changes Aug 5, 2026
DDDDDanica
DDDDDanica previously approved these changes Aug 5, 2026
@Cal-L
Cal-L dismissed stale reviews from DDDDDanica and weitingsun via a77816d August 6, 2026 17:00
weitingsun
weitingsun previously approved these changes Aug 6, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a77816d. Configure here.

Comment thread packages/remote-feature-flag-controller/src/remote-feature-flag-controller.ts Outdated

@mcmire mcmire left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@Cal-L
Cal-L added this pull request to the merge queue Aug 7, 2026
Merged via the queue into main with commit ba9a719 Aug 7, 2026
212 checks passed
@Cal-L
Cal-L deleted the feat/seed-defaults-remote-feature-flag-controller branch August 7, 2026 18:49

// Rebuild the processed remote layer from last session's effective flags by
// stripping local overrides.
const processedRemoteFeatureFlags = {

@Gudahtt Gudahtt Aug 7, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This step is unnecessary, and doesn't achieve the stated goals

There is no reason to attempt to strip out the impact of previous overrides here. And even if we wanted to, this would not achieve that goal (because we don't know what the overrides were when this state was generated).

This code is assuming the overrides are unchanged. But if that was true, why remove them only to re-apply them immediately afterwards? The only reason I can foresee for re-applying overrides is to accommodate a change in overrides, which violates the assumption made here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we really want to accommodate making the initial state of remoteFeatureFlags correct even when overrides change, we need to recalculate the feature flags from the raw values. Not from the persisted processed values.

If this is not a priority, we can simply delete this step instead.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this was a pre-existing bug though, just moved by this PR.

remoteFeatureFlags: { ...this.#processedRemoteFeatureFlags },
remoteFeatureFlags: this.#getEffectiveFeatureFlags(
this.#processedRemoteFeatureFlags,
{},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This is another pre-existing bug: this.#processedRemoteFeatureFlags may already contain overrides, because the attempt to strip them out int he constructor is ineffective. We must construct the feature flags from the raw values to remove overrides.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 - Since @davidmurdoch mentioned that he's working on updating these states, I'll reach out to coordinate on this. I contemplated on doing a refactor but is out of scope for this PR.

...this.state,
localOverrides: newLocalOverrides,
remoteFeatureFlags,
remoteFeatureFlags: this.#getEffectiveFeatureFlags(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Another pre-existing bug, where we're attempting to remove overrides incorrectly

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 - Since @davidmurdoch mentioned that he's working on updating these states, I'll reach out to coordinate on this. I contemplated on doing a refactor but is out of scope for this PR.

remoteFeatureFlags: this.#getEffectiveFeatureFlags(
redactedProcessedFlags,
),
rawRemoteFeatureFlags: redactMetaMetricsIds(remoteFeatureFlags),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this explains the other bugs.

Redacting IDs here makes it impossible to use rawRemoteFeatureFlags for any useful work. This is a mistake, and is probably what motivated the flawed attempts at removing overrides. We must redact IDs later at the point of collection, not here. We need complete raw flags in order to effectively work with overrides.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants